<?php
/**
 * SESSION: 
 * 		viewLang: changes when: user changes lang, or login/logout
 *  	userRoles, userPermissions, blockList:changes when user login/logout
 *  
 * 		Auth: userId: changes when user login/logout
 */

//require_once 'Zend/Loader.php'; //deprecated in 1.8
require_once 'Zend/Loader/Autoloader.php';

class Bootstrap
{
    public static $frontController = null;
    public static $registry = null;
    public static $cache = null;
    public static $isAjaxRequest = false;
    
    public static function run()
    {
        self::prepare();
        //if (!self::$cache->start('testpage'))
        {
            $response = self::$frontController->dispatch();
            self::sendResponse($response);
            if (SITE == 'hvn') //todo: & development mode
            {
             //   Zend_Debug::dump($_SESSION);
             //   self::log();
            }
        } 
        //die_a($response);
    }
    
    public static function prepare()
    {
        //Zend_Loader::registerAutoload(); //deprecated in 1.8
        $loader = Zend_Loader_Autoloader::getInstance();
        $loader->setFallbackAutoloader(true);
        $loader->suppressNotFoundWarnings(false);
        
        
        self::setupEnvironment();
        //self::setupCache();
        self::setupRegistry();

        Zend_Session::start();
        self::setupConfiguration();
        self::setupSession();
		
        //do we always need to setup FrontController? Yes
        self::setupFrontController();
        
        //always Response Object? No
        if (self::$isAjaxRequest) //only return json
			self::setupResponseObject();

		//always DB? Yes, because Cache is already done before, using ZF component
        self::setupDatabase();
        
        //always route? if ajax, perhaps no
        self::setupRoutes();
        
        //always? yes...
        self::setupPlugins(); //registers plugins for Hvn
        
//        if (!Zend_Registry::get('configuration')->development)
		if (Zend_Registry::get('configuration')->general->version == 1)
        	self::setupView(); //TODO: to check. this has been deferred to widgetService
        self::setupLogger();
    }

    
    public static function setupCache()
    {
        
    	$frontendOptions = array(
           'lifetime' => 3600,
           'debug_header' => false, // for debugging
           'regexps' => array(
		       // cache the whole site
       		  '(.*)' => array('cache' => true, 
       		  					'cache_with_get_variables' => true,
    						    'cache_with_session_variables'   => true,
                                'cache_with_cookie_variables'    => true,
                                'make_id_with_session_variables' => false,
                                'make_id_with_cookie_variables'  => false,
    	
    			)
       		   //'^en/article/index/search' => array('cache' => true)
    		)
			
    	);
    	
    	/*
    	$frontendOptions = array(
               'lifetime' => 30, // ( seconds )cache lifetime of 2 hours 7200/120 = 60120 phut
               'automatic_serialization' => true
		);	
		*/
    	
        $backendOptions = array(
            'cache_dir' => APP_PATH . '/cache/ZendCache/', // Directory where to put the cache files
        	'file_name_prefix' => 'zend_cache_query',
            'hashed_directory_level' => 2
        );

        // getting a Zend_Cache_Core object
        self::$cache = Zend_Cache::factory('Page',
                                         'File',
                                         $frontendOptions,
                                         $backendOptions);
                                         
		self::$cache->start();                    
    }

    public static function setupEnvironment()
    {
        //error_reporting(E_ALL|E_STRICT);
        error_reporting(E_ALL);
        ini_set('display_errors', true);
//        date_default_timezone_set('Europe/London');

        //for later use
        define('APP_PATH', dirname(__FILE__));
        define('SITE', 'archin');
        define('CLU_NS', 'Clu'); //clu session namespace
        define('AJAX_WIDGETS_NS', 'AjaxWidgets');
        define('HTMLPURIFIER_PREFIX', APP_PATH.'/library/Purifier/');
        define('WYSIWYG', 'rte');
        self::_disableMagicQuotes();
    }
    
    public static function setupFrontController()
    {
    	//front controller
        self::$frontController = Zend_Controller_Front::getInstance();
        //TODO: Remove the try&catch??
        self::$frontController->throwExceptions(true);
//        self::$frontController->throwExceptions(false);
        self::$frontController->returnResponse(true);

//        self::$frontController->setControllerDirectory('controllers');

        //modules
        self::$frontController->addModuleDirectory(APP_PATH . '/modules/');
        self::$frontController->setModuleControllerDirectoryName('controllers');
        
        // TODO default module/controller/action
        self::$frontController->setParam('prefixDefaultModule', true);
        self::$frontController->setDefaultModule('user');
        self::$frontController->setDefaultControllerName('index');
        self::$frontController->setDefaultAction('index');
        self::$frontController->setParam('disableOutputBuffering', true);
        
        //$front->setParam('disableOutputBuffering', true);
        //TODO : To remove. Not to have default ViewRenderer helper for the Controllers.
        // self::$frontController->setParam('noViewRenderer', true);
        
        //$frontController->setParam('env', APPLICATION_ENVIRONMENT);
        
        self::$frontController->setParam('registry', self::$registry);

        
        $plug = new Zend_Controller_Plugin_ActionStack;
        self::$frontController->registerPlugin($plug);
    }
    
	public static function setupResponseObject()
	{
		//request response
        $response = new Zend_Controller_Response_Http;
        //$response->renderExceptions(true);TODO
        $response->setHeader('Content-Type', 'text/html; charset=UTF-8', true);
        $response->setHeader( 'Accept-Encoding', "gzip, compress");
        self::$frontController->setResponse($response);
	}
    
    public static function setupView()
    {
        $view = new Zend_View;
        $view->setEncoding('UTF-8');
        $view->doctype('XHTML1_STRICT');
        $view->addHelperPath(
            APP_PATH . '/library/Clu/View/Helper',
            'Clu_View_Helper'
        );
        $view->setScriptPath(APP_PATH . '/');
        
        $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
        $viewRenderer->setNeverRender();
        
        Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
        
        Zend_Layout::startMvc();
        //Zend_Registry::set('cluView', $view);
        //set place holders Weight
        Zend_Registry::set('holderWeights', array());
    }

    public static function setupLogger()
    {
    
        $stream = @fopen(APP_PATH . '/logs/log.txt', 'r+', false);
        if (! $stream) {
            throw new Exception('Failed to open stream');
        }
        $writer = new Zend_Log_Writer_Stream($stream);
        $logger = new Zend_Log($writer);
    	Zend_Registry::set('logger', $logger);
    }
    
    public static function sendResponse(Zend_Controller_Response_Http $response)
    {
    	//$response->sendResponse();
    	//todo: check if there is exception first
    	if ($response->isException())
    	{
    		die($response->getException());
    	}
    	$a = $response->getBody();
    	echo $a;
    	
    }

    public static function setupRegistry()
    {
        self::$registry = new Zend_Registry(array(), ArrayObject::ARRAY_AS_PROPS);
        Zend_Registry::setInstance(self::$registry);
    }

    public static function setupConfiguration()
    {

    	$config = new Zend_Config_Ini(
            APP_PATH . '/config/'. SITE . '.config.php',
            SITE
        );

        //TODO: permissions config loading
        $permConfig = new Zend_Config(require APP_PATH . '/config/perm.config.php'); 
        self::$registry->permConfiguration = $permConfig;
                
        
        self::$registry->configuration = $config;
        if (isset($config->http)) { //TODO: Zend Proxy Credentials. Study it
            self::$registry->httpOptions = $config->http;
        }
        define('SITE_URL', $config->general->url); //http://hvn
    }

    public static function setupDatabase()
    {
        $config = self::$registry->configuration;
        $dbParams = $config->db->toArray();

//        $options = array(
//		    Zend_Db::ALLOW_SERIALIZATION => false
//		);
//		$dbParams['options'] = $options;
		/*
        if ($config->development)
        	$dbParams['profiler'] = true;
		*/
        $db = Zend_Db::factory($dbParams['adapter'], $dbParams);
        $db->query("SET NAMES 'utf8'");
        self::$registry->database = $db;
        Zend_Db_Table::setDefaultAdapter($db);
    }


    /**
     * Setup the $_SESSION['viewLang'] variable to figure out which language the user is in
     * Together with setupAcl, we have user_info as well.
     */  
    public static function setupSession()
    {
	    $sess = new Zend_Session_Namespace(CLU_NS);
	    //session fixation
        if (!isset($sess->initialized)) {
            Zend_Session::regenerateId();
            $sess->initialized = true;
        }
        unset($sess->incomingRequest);//see Clu Action Plugin predispatch TODO: remove incmoing 
        unset($sess->masterRequest);
        $params = explode('/', $_SERVER['REQUEST_URI']);
        $lang = $params[1];


        if (!in_array($lang, array('en', 'vi', 'cn', 'jp')))
        {
            //session is not set & lang is not specified then set the default Lang
            if (!isset($sess->viewLang)) 
            	$sess->viewLang = 'vi';
        }
        else if ($lang != $sess->viewLang)//in the language set
        {
        	$sess->viewLang = $lang;
        }
        if (SITE == "archin")
        	$sess->viewLang = 'en';

		Zend_Registry::set('viewLang', $sess->viewLang); //TODO: to be removed

		//user Permissions to anonymous if not yet set
        //this only happens if user first time enters the site
        if (!isset($sess->userPermissions))
        	$sess->userPermissions = Zend_Registry::get('configuration')->anon->perms;

		//set up the Translator right away
		require_once APP_PATH . '/po/' . $sess->viewLang . '.po.php'; //TODO: see if it's needed?
		if (SITE == 'gome')
			require_once APP_PATH . '/po/gome/gome.po.php';

		
        if (isset($params[3]) && strtolower($params[3]) == "ajax")
        {
        	self::$isAjaxRequest = true; //for different resource-loading option.
        	//TODO: This should be re-done in ZF 1.9 where Zend_Resource is available
        }
    }
    

    public static function setupPlugins()
    {
		/*
        $auth = Zend_Auth::getInstance();
        $acl = new Clu_Acl($auth);
//        self::$frontController->setParam('auth', $auth);
//        self::$frontController->setParam('acl', $acl);
        self::$frontController->registerPlugin(
    			     new Clu_Controller_Plugin_Acl($auth, $acl));
    
        //TODO: implement routeStartup to findout 'lang'
		*/
        self::$frontController->registerPlugin(new Clu_Controller_Plugin_Hvn());
    }
    
    //TODO: move it to plugin DisableMagicQuotes
    protected static function _disableMagicQuotes()
    {
        if (get_magic_quotes_gpc()) {
            $_GET = self::_stripSlashes($_GET);
            $_POST = self::_stripSlashes($_POST);
            $_REQUEST = self::_stripSlashes($_REQUEST);
            $_COOKIE = self::_stripSlashes($_COOKIE);
        }
    }

    protected static function _stripSlashes($value)
    {
        if (is_array($value)) {
            $value = array_map(array('Bootstrap', '_stripSlashes'), $value);
        } else {
            $value = stripslashes($value);
        }
        return $value;
    }

    
	/* TODO: depending on different master request, we might load different routes config here */
    public static function setupRoutes()
    {
    	$router = self::$frontController->getRouter();
    	$router->removeDefaultRoutes();
//    	die(APP_PATH . '/config/routes.config.ini');
		$f = APP_PATH . '/config/'.SITE.'.' . Zend_Registry::get('configuration')->general->version  . '.routes.config.ini';
		
        $config = new Zend_Config_Ini($f, 'production');
        $router = new Zend_Controller_Router_Rewrite();
        $router->addConfig($config, 'routes');

        self::$frontController->setRouter($router);
    }
        
    /**
     * @abstract : Do all the logging, profiling and such...
     * 
     */
    
    /*
    public static function log()
    {
        // find out the slowest queries
        $db = Zend_Db_Table::getDefaultAdapter();
        $profiler = $db->getProfiler();
        $totalTime    = $profiler->getTotalElapsedSecs();
        $queryCount   = $profiler->getTotalNumQueries();
        $longestTime  = 0;
        $longestQuery = null;
        
        echo "<table class='debug'><tr><td width='70%'> <b>Query</b> </td>
                   <td> <b>Time</b> </td></tr>";
        

        foreach ($profiler->getQueryProfiles() as $query) {
        	echo "<tr><td> " . $query->getQuery() . "</td>";
        	echo  "<td> " . $query->getElapsedSecs() ."</td></tr>";
        	
            if ($query->getElapsedSecs() > $longestTime) {
                $longestTime  = $query->getElapsedSecs();
                $longestQuery = $query->getQuery();
				
            }
        }
        
        echo "</table>";
        echo "<hr>";
        echo  'Executed ' . $queryCount . ' queries in ' . $totalTime .
             ' seconds' . "<br/>" ;
        echo 'Average query length: ' . $totalTime / $queryCount .
             ' seconds' . "<br/>";
        echo 'Queries per second: ' . $queryCount / $totalTime . "<br/>";
        echo 'Longest query length: ' . $longestTime . "<br/>";
        echo "Longest query: \n" . $longestQuery . "<br/>";
    }
	*/
}
